#include"lazy.h"

int main()
{
    hello("hello world");
    byebye();
    return 0;
}

#if 0

gcc -O0 -o loading lazy.c loading.c

/* objdump -d -j .plt -j .plt.sec loading */

	loading:     file format elf64-x86-64

	Disassembly of section .plt:

	0000000000001020 <.plt>:
		1020:       ff 35 92 2f 00 00       pushq  0x2f92(%rip)        # 3fb8 <_GLOBAL_OFFSET_TABLE_+0x8>
		1026:       f2 ff 25 93 2f 00 00    bnd jmpq *0x2f93(%rip)        # 3fc0 <_GLOBAL_OFFSET_TABLE_+0x10>
		102d:       0f 1f 00                nopl   (%rax)
		1030:       f3 0f 1e fa             endbr64 
		1034:       68 00 00 00 00          pushq  $0x0
		1039:       f2 e9 e1 ff ff ff       bnd jmpq 1020 <.plt>
		103f:       90                      nop
		1040:       f3 0f 1e fa             endbr64 
		1044:       68 01 00 00 00          pushq  $0x1
		1049:       f2 e9 d1 ff ff ff       bnd jmpq 1020 <.plt>
		104f:       90                      nop

	Disassembly of section .plt.sec:

	0000000000001060 <puts@plt>:
		1060:       f3 0f 1e fa             endbr64 
		1064:       f2 ff 25 5d 2f 00 00    bnd jmpq *0x2f5d(%rip)        # 3fc8 <puts@GLIBC_2.2.5>
		106b:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)

	0000000000001070 <system@plt>:
		1070:       f3 0f 1e fa             endbr64 
		1074:       f2 ff 25 55 2f 00 00    bnd jmpq *0x2f55(%rip)        # 3fd0 <system@GLIBC_2.2.5>
		107b:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)

/* disassemble main */
	(gdb) disassemble main
	Dump of assembler code for function main:
	   0x00000000000011a9 <+0>:     endbr64 
	   0x00000000000011ad <+4>:     push   %rbp
	   0x00000000000011ae <+5>:     mov    %rsp,%rbp
	   0x00000000000011b1 <+8>:     lea    0xe53(%rip),%rdi        # 0x200b
	   0x00000000000011b8 <+15>:    callq  0x1169 <hello>
	   0x00000000000011bd <+20>:    mov    $0x0,%eax
	   0x00000000000011c2 <+25>:    callq  0x1188 <byebye>
	   0x00000000000011c7 <+30>:    mov    $0x0,%eax
	   0x00000000000011cc <+35>:    pop    %rbp
	   0x00000000000011cd <+36>:    retq   
	End of assembler dump.

	main在 0x11b8 调用了puts@plt，puts@plt执行到 0x 1064 bnd jmpq *0x2f5d(%rip)	# 3fc8 <puts@GLIBC_2.2.5>，
	这个跳转是去拿got表 0x 3fc8 位置hello的地址，此值为 0x 1030 ，即跳转到.plt节那里，执行push 0。
	0为hello在 rela.plt 表中的 index，此表如下

/* readelf -r loading */
	Relocation section '.rela.dyn' at offset 0x520 contains 8 entries:
	  Offset          Info           Type           Sym. Value    Sym. Name + Addend
	000000003db0  000000000008 R_X86_64_RELATIVE                    1160
	000000003db8  000000000008 R_X86_64_RELATIVE                    1120
	000000004008  000000000008 R_X86_64_RELATIVE                    4008
	000000003fd8  000100000006 R_X86_64_GLOB_DAT 0000000000000000 _ITM_deregisterTMClone + 0
	000000003fe0  000400000006 R_X86_64_GLOB_DAT 0000000000000000 __libc_start_main@GLIBC_2.2.5 + 0
	000000003fe8  000500000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0
	000000003ff0  000600000006 R_X86_64_GLOB_DAT 0000000000000000 _ITM_registerTMCloneTa + 0
	000000003ff8  000700000006 R_X86_64_GLOB_DAT 0000000000000000 __cxa_finalize@GLIBC_2.2.5 + 0

	Relocation section '.rela.plt' at offset 0x608 contains 2 entries:
	  Offset          Info           Type           Sym. Value    Sym. Name + Addend
	000000003fc8  000200000007 R_X86_64_JUMP_SLO 0000000000000000 puts@GLIBC_2.2.5 + 0
	000000003fd0  000300000007 R_X86_64_JUMP_SLO 0000000000000000 system@GLIBC_2.2.5 + 0


	第一列offset为 puts 在 loading 中被引用位置，为0x 3fc8 ，指向的并非代码段，而是got表。
	因此，重定位过程重写的并非代码，而是数据段的got表相应项。

	push 0后，再跳转到.plt开始0x 1020 ，调用相关过程，这段逻辑的作用应该是——对puts进行重定位，把重定位的后的地址填进got表，
	下次再去got拿地址就是重定位后的puts地址，而不用重复上面这个过程了。
	
	懒加载理论上是这样，代码逻辑也是这样，然而这段demo并没有这样执行，它绕过了懒加载，
	程序启动之初就通过libld.so重定位了动态库中的函数地址，修改了got表，所以，不会去执行懒加载的逻辑。
	
	验证如下

	让 loading 停在入口处，在got表中的byebye地址处下内存断点，如下，

/* gdb loading */
	gdb loading

	(gdb) starti

		Starting program: /home/wangzhijun/work/ac-code/reverse/relocation/lazy-loading/loading 

		Program stopped.
		0x00007ffff7fd0100 in ?? () from /lib64/ld-linux-x86-64.so.2

	(gdb) info files

		Symbols from "/home/wangzhijun/work/ac-code/reverse/relocation/lazy-loading/loading".
		Native process:
				Using the running image of child process 465163.
				While running this, GDB does not access memory from...
		Local exec file:
				'/home/wangzhijun/work/ac-code/reverse/relocation/lazy-loading/loading', file type elf64-x86-64.
				Entry point: 0x555555555060
				0x0000555555554318 - 0x0000555555554334 is .interp
				0x0000555555554338 - 0x0000555555554358 is .note.gnu.property
				0x0000555555554358 - 0x000055555555437c is .note.gnu.build-id
				0x000055555555437c - 0x000055555555439c is .note.ABI-tag
				0x00005555555543a0 - 0x00005555555543c4 is .gnu.hash
				0x00005555555543c8 - 0x0000555555554488 is .dynsym
				0x0000555555554488 - 0x0000555555554511 is .dynstr
				0x0000555555554512 - 0x0000555555554522 is .gnu.version
				0x0000555555554528 - 0x0000555555554548 is .gnu.version_r
				0x0000555555554548 - 0x0000555555554608 is .rela.dyn
				0x0000555555554608 - 0x0000555555554638 is .rela.plt
				0x0000555555555000 - 0x000055555555501b is .init
				0x0000555555555020 - 0x0000555555555050 is .plt					//
				0x0000555555555050 - 0x0000555555555060 is .plt.got				// 
				0x0000555555555060 - 0x0000555555555080 is .plt.sec				//
				0x0000555555555080 - 0x0000555555555245 is .text				//
				0x0000555555555248 - 0x0000555555555255 is .fini
				0x0000555555556000 - 0x0000555555556017 is .rodata
				0x0000555555556018 - 0x000055555555606c is .eh_frame_hdr
				0x0000555555556070 - 0x00005555555561b8 is .eh_frame
				0x0000555555557db0 - 0x0000555555557db8 is .init_array
				0x0000555555557db8 - 0x0000555555557dc0 is .fini_array
				0x0000555555557dc0 - 0x0000555555557fb0 is .dynamic
				0x0000555555557fb0 - 0x0000555555558000 is .got					//
				0x0000555555558000 - 0x0000555555558010 is .data
				0x0000555555558010 - 0x0000555555558018 is .bss
				0x00007ffff7fcf2a8 - 0x00007ffff7fcf2c8 is .note.gnu.property in /lib64/ld-linux-x86-64.so.2
				0x00007ffff7fcf2c8 - 0x00007ffff7fcf2ec is .note.gnu.build-id in /lib64/ld-linux-x86-64.so.2
				0x00007ffff7fcf2f0 - 0x00007ffff7fcf3c4 is .hash in /lib64/ld-linux-x86-64.so.2
				0x00007ffff7fcf3c8 - 0x00007ffff7fcf4c0 is .gnu.hash in /lib64/ld-linux-x86-64.so.2
				0x00007ffff7fcf4c0 - 0x00007ffff7fcf7f0 is .dynsym in /lib64/ld-linux-x86-64.so.2
				0x00007ffff7fcf7f0 - 0x00007ffff7fcfa14 is .dynstr in /lib64/ld-linux-x86-64.so.2
				0x00007ffff7fcfa14 - 0x00007ffff7fcfa58 is .gnu.version in /lib64/ld-linux-x86-64.so.2
				0x00007ffff7fcfa58 - 0x00007ffff7fcfafc is .gnu.version_d in /lib64/ld-linux-x86-64.so.2
				0x00007ffff7fcfb00 - 0x00007ffff7fcff20 is .rela.dyn in /lib64/ld-linux-x86-64.so.2
				0x00007ffff7fcff20 - 0x00007ffff7fcffc8 is .rela.plt in /lib64/ld-linux-x86-64.so.2
				0x00007ffff7fd0000 - 0x00007ffff7fd0080 is .plt in /lib64/ld-linux-x86-64.so.2
				0x00007ffff7fd0080 - 0x00007ffff7fd0090 is .plt.got in /lib64/ld-linux-x86-64.so.2
				0x00007ffff7fd0090 - 0x00007ffff7fd0100 is .plt.sec in /lib64/ld-linux-x86-64.so.2
				0x00007ffff7fd0100 - 0x00007ffff7ff2674 is .text in /lib64/ld-linux-x86-64.so.2
				0x00007ffff7ff3000 - 0x00007ffff7ff7dbb is .rodata in /lib64/ld-linux-x86-64.so.2
				0x00007ffff7ff7dbb - 0x00007ffff7ff7dbc is .stapsdt.base in /lib64/ld-linux-x86-64.so.2
				0x00007ffff7ff7dbc - 0x00007ffff7ff84e0 is .eh_frame_hdr in /lib64/ld-linux-x86-64.so.2
				0x00007ffff7ff84e0 - 0x00007ffff7ffaccc is .eh_frame in /lib64/ld-linux-x86-64.so.2
				0x00007ffff7ffc520 - 0x00007ffff7ffce64 is .data.rel.ro in /lib64/ld-linux-x86-64.so.2
				0x00007ffff7ffce68 - 0x00007ffff7ffcfd8 is .dynamic in /lib64/ld-linux-x86-64.so.2
				0x00007ffff7ffcfd8 - 0x00007ffff7ffcfe8 is .got in /lib64/ld-linux-x86-64.so.2
				0x00007ffff7ffd000 - 0x00007ffff7ffd050 is .got.plt in /lib64/ld-linux-x86-64.so.2
				0x00007ffff7ffd060 - 0x00007ffff7ffdff8 is .data in /lib64/ld-linux-x86-64.so.2
				0x00007ffff7ffe000 - 0x00007ffff7ffe190 is .bss in /lib64/ld-linux-x86-64.so.2
				0x00007ffff7fcd120 - 0x00007ffff7fcd168 is .hash in system-supplied DSO at 0x7ffff7fcd000
				0x00007ffff7fcd168 - 0x00007ffff7fcd1c4 is .gnu.hash in system-supplied DSO at 0x7ffff7fcd000
				0x00007ffff7fcd1c8 - 0x00007ffff7fcd300 is .dynsym in system-supplied DSO at 0x7ffff7fcd000
				0x00007ffff7fcd300 - 0x00007ffff7fcd38b is .dynstr in system-supplied DSO at 0x7ffff7fcd000
				0x00007ffff7fcd38c - 0x00007ffff7fcd3a6 is .gnu.version in system-supplied DSO at 0x7ffff7fcd000
				0x00007ffff7fcd3a8 - 0x00007ffff7fcd3e0 is .gnu.version_d in system-supplied DSO at 0x7ffff7fcd000
				0x00007ffff7fcd3e0 - 0x00007ffff7fcd500 is .dynamic in system-supplied DSO at 0x7ffff7fcd000
				0x00007ffff7fcd500 - 0x00007ffff7fcd554 is .note in system-supplied DSO at 0x7ffff7fcd000
				0x00007ffff7fcd554 - 0x00007ffff7fcd598 is .eh_frame_hdr in system-supplied DSO at 0x7ffff7fcd000
				0x00007ffff7fcd598 - 0x00007ffff7fcd6d0 is .eh_frame in system-supplied DSO at 0x7ffff7fcd000
				0x00007ffff7fcd6d0 - 0x00007ffff7fcde9c is .text in system-supplied DSO at 0x7ffff7fcd000
				0x00007ffff7fcde9c - 0x00007ffff7fcdf93 is .altinstructions in system-supplied DSO at 0x7ffff7fcd000
				0x00007ffff7fcdf93 - 0x00007ffff7fcdfdf is .altinstr_replacement in system-supplied DSO at 0x7ffff7fcd000

	(gdb) x /10xw 0x0000555555557fb0

		0x555555557fb0: 0x00003dc0      0x00000000      0x00000000      0x00000000
		0x555555557fc0: 0x00000000      0x00000000      0x00001030      0x00000000
		0x555555557fd0 <system@got.plt>:        0x00001040      0x00000000

	(gdb) watch *(void *)0x555555557fd0
		Attempt to dereference a generic pointer.

	(gdb) watch *(int *)0x555555557fd0
		Hardware watchpoint 1: *(int *)0x555555557fd0

	(gdb) c
		Continuing.

		Hardware watchpoint 1: *(int *)0x555555557fd0

		Old value = 4160
		New value = -136244208
		0x00007ffff7fdcf6e in ?? () from /lib64/ld-linux-x86-64.so.2

		可以看到，刚开始，got中byebye@got.plt内容为0x1040，中断后，知道byebye的got表记录地址原先是4160，
		即0x1040，现在被修改为-134532808，
		通过 x /1xg 0x555555557fd0 查看现在byebye@got.plt的内容，结果是 0x00007ffff7e11410

	(gdb) x /1xg 0x555555557fd0
		0x555555557fd0 <system@got.plt>:        0x00007ffff7e11410

		这个地址是哪里呢，就是byebye函数现在加载在进程空间的地址

	(gdb) x /8i 0x00007ffff7e11410
	   0x7ffff7e11410:      endbr64 
	   0x7ffff7e11414:      test   %rdi,%rdi
	   0x7ffff7e11417:      je     0x7ffff7e11420
	   0x7ffff7e11419:      jmpq   0x7ffff7e10e50
	   0x7ffff7e1141e:      xchg   %ax,%ax
	   0x7ffff7e11420:      sub    $0x8,%rsp
	   0x7ffff7e11424:      lea    0x162187(%rip),%rdi        # 0x7ffff7f735b2
	   0x7ffff7e1142b:      callq  0x7ffff7e10e50

	由此可知，在main函数调用byebye@plt之前，libld.so已经修改了test的got表，把重定位后的地址填进去了。
	并非如其他说的那样首次调用时才懒加载。

#endif
